<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>超级密码管理系统</title>
  <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
  <script src="https://unpkg.com/crypto-js@4.1.1/crypto-js.js"></script>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
      font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    }
    
    body {
      background: linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c);
      min-height: 100vh;
      display: flex;
      justify-content: center;
      align-items: center;
      padding: 20px;
      color: #333;
      overflow: hidden;
    }
    
    .app-container {
      width: 100%;
      max-width: 1000px;
      background: rgba(255, 255, 255, 0.92);
      border-radius: 20px;
      box-shadow: 0 15px 30px rgba(0, 0, 0, 0.3);
      overflow: hidden;
    }
    
    .page {
      padding: 30px;
      min-height: 500px;
    }
    
    /* 登录页面样式 */
    .login-container {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      height: 100%;
      padding: 40px;
    }
    
    .logo {
      font-size: 48px;
      margin-bottom: 30px;
      color: #2c3e50;
    }
    
    .login-form {
      width: 100%;
      max-width: 400px;
      background: white;
      padding: 40px;
      border-radius: 15px;
      box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
    }
    
    .input-group {
      margin-bottom: 25px;
      position: relative;
    }
    
    .input-group label {
      display: block;
      margin-bottom: 8px;
      font-weight: 500;
      color: #2c3e50;
    }
    
    .input-group input {
      width: 100%;
      padding: 14px 15px;
      border: 2px solid #ddd;
      border-radius: 10px;
      font-size: 16px;
      transition: all 0.3s;
    }
    
    .input-group input:focus {
      border-color: #3498db;
      box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.2);
      outline: none;
    }
    
    .btn {
      padding: 14px 20px;
      background: #3498db;
      color: white;
      border: none;
      border-radius: 10px;
      font-size: 16px;
      font-weight: 600;
      cursor: pointer;
      transition: all 0.3s;
      width: 100%;
    }
    
    .btn:hover {
      background: #2980b9;
      transform: translateY(-2px);
      box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1);
    }
    
    /* 主页面样式 */
    .header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 25px;
      padding-bottom: 15px;
      border-bottom: 2px solid #eee;
    }
    
    .header h1 {
      color: #2c3e50;
      font-size: 28px;
    }
    
    .action-buttons button {
      margin-left: 10px;
      padding: 10px 15px;
      border-radius: 10px;
      border: none;
      background: #3498db;
      color: white;
      font-size: 16px;
      cursor: pointer;
      transition: all 0.3s;
    }
    
    .action-buttons button:hover {
      background: #2980b9;
      transform: translateY(-2px);
    }
    
    .action-buttons .export-btn {
      background: #27ae60;
    }
    
    .action-buttons .export-btn:hover {
      background: #219653;
    }

    .action-buttons .logout-btn {
      background: #f34b4b;
    }
    
    .action-buttons .logout-btn:hover {
      background: #f30f0f;
    }

    .action-buttons .import-btn {
      background: #def03c;
    }
    
    .action-buttons .import-btn:hover {
      background: #d9f00e;
    }
    
    .area-list {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
      gap: 25px;
    }
    
    .area-item {
      background: white;
      border-radius: 15px;
      padding: 20px;
      box-shadow: 0 5px 15px rgba(0, 0, 0, 0.08);
      transition: all 0.3s;
      border: 2px solid #e0e0e0;
    }
    
    .area-item:hover {
      transform: translateY(-5px);
      box-shadow: 0 8px 20px rgba(0, 0, 0, 0.12);
      border-color: #3498db;
    }
    
    .area-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 15px;
      padding-bottom: 10px;
      border-bottom: 1px solid #eee;
    }
    
    .area-title {
      font-size: 20px;
      font-weight: 600;
      color: #2c3e50;
    }
    
    .area-actions button {
      background: none;
      border: none;
      margin-left: 8px;
      cursor: pointer;
      color: #7f8c8d;
      font-size: 16px;
      transition: all 0.2s;
    }
    
    .area-actions button:hover {
      color: #3498db;
    }
    
    .notes-container {
      margin: 15px 0;
    }
    
    .note-item {
      background: #f8f9fa;
      padding: 10px;
      border-radius: 8px;
      margin-bottom: 8px;
      position: relative;
      transition: all 0.2s;
      border: 1px solid #eee;
    }
    
    .note-item:hover {
      background: #e3f2fd;
      border-color: #bbdefb;
    }
    
    .note-item:active {
      background: #bbdefb;
    }
    
    .rules-container {
      margin: 15px 0;
      padding: 15px;
      background: #f8f9fa;
      border-radius: 10px;
    }
    
    .rule-item {
      margin-bottom: 8px;
      display: flex;
      align-items: center;
    }
    
    .rule-item input {
      margin-right: 8px;
    }
    
    .password-display {
      display: flex;
      align-items: center;
      background: #f8f9fa;
      border-radius: 10px;
      padding: 12px;
      margin-top: 15px;
    }
    
    .password-display input {
      flex: 1;
      border: none;
      background: none;
      font-family: monospace;
      font-size: 16px;
      padding: 5px;
    }
    
    .password-actions {
      display: flex;
    }
    
    .password-actions button {
      background: none;
      border: none;
      margin-left: 10px;
      cursor: pointer;
      color: #7f8c8d;
      font-size: 18px;
      transition: all 0.2s;
    }
    
    .password-actions button:hover {
      color: #3498db;
    }
    
    /* 编辑面板样式 */
    .modal-overlay {
      position: fixed;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      background: rgba(0, 0, 0, 0.7);
      display: flex;
      justify-content: center;
      align-items: center;
      z-index: 1000;
      overflow: auto;
      padding: 20px;
    }
    
    .edit-panel {
      background: white;
      width: 90%;
      max-width: 600px;
      border-radius: 20px;
      padding: 30px;
      box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
      max-height: 90vh;
      display: flex;
      flex-direction: column;
    }
    
    .panel-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 25px;
      padding-bottom: 15px;
      border-bottom: 2px solid #eee;
      flex-shrink: 0;
    }
    
    .panel-title {
      font-size: 24px;
      color: #2c3e50;
    }
    
    .form-group {
      margin-bottom: 20px;
    }
    
    .form-group label {
      display: block;
      margin-bottom: 8px;
      font-weight: 500;
    }
    
    .form-group input {
      width: 100%;
      padding: 12px 15px;
      border: 2px solid #ddd;
      border-radius: 10px;
      font-size: 16px;
    }
    
    /* 密码长度滑块样式 */
    .length-control {
      margin-top: 15px;
      padding: 15px;
      background: #f8f9fa;
      border-radius: 10px;
    }
    
    .length-header {
      display: flex;
      justify-content: space-between;
      margin-bottom: 10px;
    }
    
    .length-value {
      font-weight: bold;
      color: #3498db;
      font-size: 18px;
      min-width: 40px;
      text-align: right;
    }
    
    .slider-container {
      position: relative;
      height: 30px;
      display: flex;
      align-items: center;
    }
    
    .slider-container input[type="range"] {
      width: 100%;
      height: 6px;
      -webkit-appearance: none;
      background: linear-gradient(to right, #3498db, #2ecc71);
      border-radius: 3px;
      outline: none;
    }
    
    .slider-container input[type="range"]::-webkit-slider-thumb {
      -webkit-appearance: none;
      width: 22px;
      height: 22px;
      border-radius: 50%;
      background: #3498db;
      cursor: pointer;
      box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
      transition: all 0.2s;
    }
    
    .slider-container input[type="range"]::-webkit-slider-thumb:hover {
      transform: scale(1.2);
      background: #2980b9;
    }
    
    .length-indicators {
      display: flex;
      justify-content: space-between;
      margin-top: 5px;
      font-size: 12px;
      color: #7f8c8d;
    }
        
    .notes-list {
      margin: 15px 0;
    }
    
    .note-input {
      display: flex;
      margin-bottom: 10px;
    }
    
    .note-input input {
      flex: 1;
      padding: 10px;
      border: 2px solid #ddd;
      border-radius: 8px 0 0 8px;
    }
    
    .note-input button {
      padding: 10px 15px;
      background: #e74c3c;
      color: white;
      border: none;
      border-radius: 0 8px 8px 0;
      cursor: pointer;
    }
    
    .panel-body {
      overflow-y: auto;
      flex: 1;
      padding: 5px 0;
      scrollbar-width: thin;
      scrollbar-color: #3498db #f1f1f1;
    }
    
    .panel-body::-webkit-scrollbar {
      width: 8px;
    }
    
    .panel-body::-webkit-scrollbar-track {
      background: #f1f1f1;
      border-radius: 10px;
    }
    
    .panel-body::-webkit-scrollbar-thumb {
      background: #3498db;
      border-radius: 10px;
    }
    
    .panel-body::-webkit-scrollbar-thumb:hover {
      background: #2980b9;
    }

    .panel-actions {
      display: flex;
      justify-content: flex-end;
      margin-top: 25px;
    }
    
    .panel-actions button {
      padding: 12px 20px;
      margin-left: 15px;
      border: none;
      border-radius: 10px;
      font-size: 16px;
      font-weight: 600;
      cursor: pointer;
      transition: all 0.3s;
    }
    
    .confirm-btn {
      background: #27ae60;
      color: white;
    }
    
    .cancel-btn {
      background: #e74c3c;
      color: white;
    }
    
    .confirm-btn:hover {
      background: #219653;
    }
    
    .cancel-btn:hover {
      background: #c0392b;
    }
    
    /* 删除确认框样式 */
    .delete-confirm {
      background: white;
      width: 90%;
      max-width: 400px;
      border-radius: 15px;
      padding: 30px;
      text-align: center;
    }
    
    .delete-confirm h3 {
      margin-bottom: 20px;
      color: #2c3e50;
    }
    
    .delete-confirm p {
      margin-bottom: 25px;
      font-size: 18px;
      color: #7f8c8d;
    }
    
    .confirm-buttons button {
      padding: 12px 25px;
      margin: 0 10px;
      border: none;
      border-radius: 10px;
      font-size: 16px;
      font-weight: 600;
      cursor: pointer;
    }
    
    /* 动画效果 */
    .fade-enter-active, .fade-leave-active {
      transition: opacity 0.3s;
    }
    
    .fade-enter-from, .fade-leave-to {
      opacity: 0;
    }
    
    .long-press {
      background: #bbdefb !important;
      transform: scale(1.05);
    }
    
    .toast {
      position: fixed;
      bottom: 30px;
      left: 50%;
      transform: translateX(-50%);
      background: #27ae60;
      color: white;
      padding: 15px 30px;
      border-radius: 10px;
      box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
      z-index: 1001;
      animation: fadeInOut 3s ease-in-out;
    }

    @keyframes fadeInOut {
      0%, 100% { opacity: 0; transform: translate(-50%, 20px); }
      10%, 90% { opacity: 1; transform: translate(-50%, 0); }
    }

    /* 滚动提示 */
    .scroll-hint {
      position: absolute;
      bottom: 15px;
      left: 0;
      right: 0;
      text-align: center;
      color: #7f8c8d;
      font-size: 14px;
      opacity: 0.8;
      animation: pulse 2s infinite;
    }
    
    @keyframes pulse {
      0%, 100% { opacity: 0.5; }
      50% { opacity: 1; }
    }

  </style>
</head>
<body>
  <div id="app">
    <div class="app-container">
      <!-- 登录页面 -->
      <div class="page" v-if="currentPage === 'login'">
        <div class="login-container">
          <div class="logo">
            <i class="fas fa-lock"></i>
          </div>
          <div class="login-form">
            <div class="input-group">
              <label for="username">输入账号</label>
              <input
                type="text"
                id="username"
                v-model="username"
                placeholder="请输入您的输入账号"
                @keyup.enter="login"
              >
              <label for="password">输入密码</label>
              <input
                type="password"
                id="password" 
                v-model="password" 
                placeholder="请输入您的密码"
                @keyup.enter="login"
              >
            </div>
            <button class="btn" @click="login">登录</button>
          </div>
        </div>
      </div>
      
      <!-- 主页面 -->
      <div class="page" v-if="currentPage === 'main'">
        <div class="header">
          <h1>超级密码管理系统</h1>
          <div class="action-buttons">
            <button @click="openAddPanel">
              <i class="fas fa-plus"></i> 添加
            </button>
            <button class="import-btn" @click="importData">
              <i class="fas fa-upload"></i> 导入
            </button>
            <button class="export-btn" @click="exportData">
              <i class="fas fa-download"></i> 导出
            </button>
            <button class="logout-btn" @click="Logout">
              <i class="fas fa-logout"></i> 登出
            </button>
          </div>
        </div>
        
        <div class="area-list">
          <div class="area-item" v-for="(item, index) in areaList" :key="index">
            <div class="area-header">
              <div class="area-title">{{ item.name }}</div>
              <div class="area-actions">
                <button @click="openEditPanel(index)" title="编辑">
                  <i class="fas fa-edit"></i>
                </button>
                <button @click="confirmDelete(index)" title="删除">
                  <i class="fas fa-trash"></i>
                </button>
              </div>
            </div>
            
            <div class="notes-container">
              <div 
                class="note-item"
                v-for="(note, noteIndex) in item.notes"
                :key="noteIndex"
                :class="{ 'long-press': longPressIndex === noteIndex }"
                @touchend="copyPassword(note)"
                @mouseup="copyPassword(note)"
              >
                {{ note }}
              </div>
            </div>
            
            <!-- <div class="rules-container">
              <div class="length-control">
                <div class="length-header">
                  <div>密码长度</div>
                  <div class="length-value">{{ item.rules.length }}</div>
                </div>
                <div class="slider-container">
                  <input 
                    type="range" 
                    min="1" 
                    max="64" 
                    v-model.number="item.rules.length"
                    disabled
                  >
                </div>
                <div class="length-indicators">
                  <span>1</span>
                  <span>64</span>
                </div>
              </div>
              <div class="rule-item" v-for="(rule, key) in passwordRules" :key="key">
                <input type="checkbox" :id="`rule-${index}-${key}`" v-model="item.rules[key]" disabled>
                <label :for="`rule-${index}-${key}`">{{ rule.label }}</label>
              </div>
            </div> -->
            
            <div class="password-display">
              <input :type="item.showPassword ? 'text' : 'password'" :value="generatePassword(item.rules,item.name)" readonly>
              <div class="password-actions">
                <button @click="togglePasswordVisibility(index)" :title="item.showPassword ? '隐藏密码' : '显示密码'">
                  <i :class="item.showPassword ? 'fas fa-eye-slash' : 'fas fa-eye'"></i>
                </button>
                <button @click="copyPassword(generatePassword(item.rules,item.name))" title="复制密码">
                  <i class="fas fa-copy"></i>
                </button>
              </div>
            </div>
          </div>
        </div>
      </div>
      
      <!-- 添加/编辑面板 -->
      <transition name="fade">
        <div class="modal-overlay" v-if="showEditPanel" @click.self="closeEditPanel">
          <div class="edit-panel">
            <div class="panel-header">
              <h2 class="panel-title">{{ isEditing ? '编辑区号' : '添加新区号' }}</h2>
            </div>
            <div class="form-group">
              <label for="area-name">区号名称</label>
              <input type="text" id="area-name" v-model="currentItem.name" placeholder="输入区号名称">
            </div>

            <div class="panel-body">

            
            <div class="form-group">
              <label>备注项</label>
              <div class="notes-list">
                <div class="note-item" v-for="(note, index) in currentItem.notes" :key="index">
                  <div class="note-input">
                    <input type="text" v-model="currentItem.notes[index]" placeholder="输入备注内容">
                    <button @click="removeNote(index)"><i class="fas fa-times"></i></button>
                  </div>
                </div>
                <button class="btn" @click="addNote" style="margin-top: 10px;">
                  <i class="fas fa-plus"></i> 添加备注
                </button>
              </div>
            </div>
            
            <div class="form-group">
              <label>密码规则</label>
              <div class="rules-container">
                <div class="length-control">
                  <div class="length-header">
                    <div>密码长度</div>
                    <div class="length-value">{{ currentItem.rules.length }}</div>
                  </div>
                  <div class="slider-container">
                    <input 
                      type="range" 
                      min="1" 
                      max="64" 
                      v-model.number="currentItem.rules.length"
                    >
                  </div>
                  <div class="length-indicators">
                    <span>1</span>
                    <span>64</span>
                  </div>
                </div>

                <div class="rule-item" v-for="(rule, key) in passwordRules" :key="key">
                  <input type="checkbox" :id="`rule-${key}`" v-model="currentItem.rules[key]">
                  <label :for="`rule-${key}`">{{ rule.label }}</label>
                </div>

                <label for="extra_chars">考虑字符</label>
                <input type="text" id="extra_chars" v-model="currentItem.rules.extra_chars" placeholder="输入考虑字符">
                <label for="ignore_chars">忽略字符</label>
                <input type="text" id="ignore_chars" v-model="currentItem.rules.ignore_chars" placeholder="输入忽略字符">

              </div>
            </div>
            
          </div>

            <div class="form-group">
              <label>生成的密码</label>
              <div class="password-display">
                <input :type="showGeneratedPassword ? 'text' : 'password'" :value="generatePassword(currentItem.rules,currentItem.name)" readonly>
                <div class="password-actions">
                  <button @click="showGeneratedPassword = !showGeneratedPassword" :title="showGeneratedPassword ? '隐藏密码' : '显示密码'">
                    <i :class="showGeneratedPassword ? 'fas fa-eye-slash' : 'fas fa-eye'"></i>
                  </button>
                </div>
              </div>
            </div>
            

            <div class="panel-actions">
              <button class="cancel-btn" @click="closeEditPanel">取消</button>
              <button class="confirm-btn" @click="saveItem">{{ isEditing ? '保存修改' : '添加区号' }}</button>
            </div>

            <div class="scroll-hint" v-if="showScrollHint">
              <i class="fas fa-chevron-down"></i> 上下滑动查看更多内容
            </div>
          </div>
        </div>
      </transition>
      
      <!-- 删除确认框 -->
      <transition name="fade">
        <div class="modal-overlay" v-if="showDeleteConfirm">
          <div class="delete-confirm">
            <h3>确认删除</h3>
            <p>确定要删除 "{{ deleteItemName }}" 吗？此操作不可恢复。</p>
            <div class="confirm-buttons">
              <button class="cancel-btn" @click="showDeleteConfirm = false">取消</button>
              <button class="confirm-btn" @click="deleteItem">确认删除</button>
            </div>
          </div>
        </div>
      </transition>
      
      <!-- 复制成功提示 -->
      <transition name="fade">
        <div class="toast" v-if="showToast">
          已复制到剪贴板
        </div>
      </transition>
    </div>
  </div>

  <script>
    const { createApp, ref, reactive, computed, watch, onMounted } = Vue;
    
    function getPasswordStrength(password) {
        const tests = [
            /.{8,}/,                        // 长度至少8
            /[a-z]/,                         // 包含小写字母
            /[A-Z]/,                         // 包含大写字母
            /\d/,                            // 包含数字
            /[@$!%*?&]/                      // 包含特殊字符
        ];
        
        let strength = 0;
        tests.forEach(regex => {
            if (regex.test(password)) strength++;
        });
        
        return strength; // 0-5，数值越大强度越高
    }

    createApp({
      setup() {
        // 状态管理
        const currentPage = ref('login');
        const username = ref('');
        const password = ref('');
        const areaList = ref([]);
        const showEditPanel = ref(false);
        const isEditing = ref(false);
        const editingIndex = ref(-1);
        const showDeleteConfirm = ref(false);
        const deleteIndex = ref(-1);
        const showToast = ref(false);
        const showGeneratedPassword = ref(false);
        const longPressTimer = ref(null);
        const longPressIndex = ref(-1);
        const showScrollHint = ref(false);

        // 密码规则定义
        const passwordRules = reactive({
          uppercase: { label: "包含大写字母" },
          lowercase: { label: "包含小写字母" },
          numbers: { label: "包含数字" },
          space : { label: "空格"},
          symbols1: {label: "-"},
          symbols2: {label: "_"},
          symbols3: {label: "&/,^@.#:%\='$!*`;+"},
          symbols4: {label: "[](){}<>"},
          leastOne : { label: "每种至少有一个字符"},
        });
        
        // 当前编辑项
        const currentItem = reactive({
          name: '',
          notes: [],
          rules: {
            length: 8,
            uppercase: false,
            lowercase: false,
            numbers: false,
            space : false,
            symbols1 : false,
            symbols2 : false,
            symbols3 : false,
            symbols4 : false,
            leastOne : false,
            extra_chars : "",
            ignore_chars : "",
          }
        });

        const globObj = {
          username : "",
          password : "",
        };
        
        // 登录功能
        const login = () => {
          if(username.value.length < 4) {
            alert('用户名长度至少为4位');
            return;
          }
          if (password.value.length >= 8) {
            if(getPasswordStrength(password.value) >= 4) {

              var sha_password = CryptoJS.SHA256(password.value + "_login").toString();

              var login_key = "login:" + username.value;

              var oldPassword = localStorage.getItem(login_key);
              if(oldPassword != null && oldPassword != sha_password) {
                alert("已存在账号信息,并且密码不正确");
                return;
              }

              localStorage.setItem(login_key, sha_password);

              globObj.username = username.value;
              globObj.password = CryptoJS.SHA256(password.value + "_1234567890abcdefghijklmn").toString();

              loadAreaList();
              currentPage.value = 'main';
            } else {
              alert("密码强度不足");
            }
          } else {
            alert('密码长度至少为8位');
          }
        };
        
        // 从localStorage加载区号列表
        const loadAreaList = () => {
          const savedList = localStorage.getItem('areaList:' + globObj.username);
          if (savedList) {
            try {
              var bytes = CryptoJS.AES.decrypt(savedList, globObj.password);
              var strJson = bytes.toString(CryptoJS.enc.Utf8);
              areaList.value = JSON.parse(strJson);
            } catch (e) {
              areaList.value = [];
              console.error('解析区号列表失败:', e);
            }
          }
        };
        
        // 保存区号列表到localStorage
        const saveAreaList = () => {
          var strJson = CryptoJS.AES.encrypt(JSON.stringify(areaList.value), globObj.password).toString();
          localStorage.setItem('areaList:' + globObj.username, strJson);
        };
        
        // 打开添加面板
        const openAddPanel = () => {
          resetCurrentItem();
          isEditing.value = false;
          showEditPanel.value = true;
          showGeneratedPassword.value = false;
          showScrollHint.value = true;

          // 3秒后隐藏滚动提示
          setTimeout(() => {
            showScrollHint.value = false;
          }, 3000);
        };
        
        // 打开编辑面板
        const openEditPanel = (index) => {
          const item = areaList.value[index];
          currentItem.name = item.name;
          currentItem.notes = [...item.notes];
          currentItem.rules = {...item.rules};
          editingIndex.value = index;
          isEditing.value = true;
          showEditPanel.value = true;
          showGeneratedPassword.value = false;

          showScrollHint.value = true;
          
          // 3秒后隐藏滚动提示
          setTimeout(() => {
            showScrollHint.value = false;
          }, 3000);          
        };
        
        // 关闭编辑面板
        const closeEditPanel = () => {
          showEditPanel.value = false;
        };
        
        // 重置当前编辑项
        const resetCurrentItem = () => {
          currentItem.name = '';
          currentItem.notes = [];
          currentItem.rules = {
            length: 8,
            uppercase: false,
            lowercase: false,
            numbers: false,
            space : false,
            symbols1 : false,
            symbols2 : false,
            symbols3 : false,
            symbols4 : false,
            leastOne : false,
            extra_chars : "",
            ignore_chars : "",
          };
        };
        
        // 添加备注项
        const addNote = () => {
          currentItem.notes.push('');
        };
        
        // 删除备注项
        const removeNote = (index) => {
          currentItem.notes.splice(index, 1);
        };
        
        // 保存项目
        const saveItem = () => {
          if (!currentItem.name.trim()) {
            alert('请输入区号名称');
            return;
          }
          
          const item = {
            name: currentItem.name,
            notes: [...currentItem.notes.filter(note => note.trim())],
            rules: {...currentItem.rules},
            showPassword: false
          };
          
          if (isEditing.value) {
            areaList.value[editingIndex.value] = item;
          } else {
            areaList.value.push(item);
          }
          
          saveAreaList();
          closeEditPanel();
        };
        
        // 确认删除
        const confirmDelete = (index) => {
          deleteIndex.value = index;
          showDeleteConfirm.value = true;
        };
        
        // 删除项目
        const deleteItem = () => {
          areaList.value.splice(deleteIndex.value, 1);
          saveAreaList();
          showDeleteConfirm.value = false;
        };
        
        // 切换密码可见性
        const togglePasswordVisibility = (index) => {
          areaList.value[index].showPassword = !areaList.value[index].showPassword;
        };
        
        // 复制密码到剪贴板
        const copyPassword = (text) => {
          navigator.clipboard.writeText(text).then(() => {
            showToastMessage();
          });
        };
        
        // 显示复制成功提示
        const showToastMessage = () => {
          showToast.value = true;
          setTimeout(() => {
            showToast.value = false;
          }, 2000);
        };
        
        // 长按复制功能
        const startLongPress = (text, index, event) => {
          event.preventDefault();
          longPressIndex.value = index;
          
          longPressTimer.value = setTimeout(() => {
            copyPassword(text);
            longPressIndex.value = -1;
          }, 800);
        };
        
        const endLongPress = () => {
          if (longPressTimer.value) {
            clearTimeout(longPressTimer.value);
            longPressTimer.value = null;
          }
          longPressIndex.value = -1;
        };
        
        // 导出数据
        const exportData = () => {
          if (!globObj.password) {
            alert('请先登录以导出数据');
            return;
          }
          
          const data = {
            timestamp: new Date().toISOString(),
            areaList: areaList.value
          };
          
          try {
            // 使用AES加密数据
            const encrypted = CryptoJS.AES.encrypt(
              JSON.stringify(data), 
              globObj.password,
            ).toString();
            
            // 创建下载链接
            const blob = new Blob([encrypted], { type: 'text/plain' });
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = globObj.username + `_${new Date().toISOString().slice(0, 10)}.data`;
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
            
            alert('数据导出成功！');
          } catch (error) {
            console.error('导出失败:', error);
            alert('数据导出失败，请重试');
          }
        };

        // 导入数据
        const importData = () => {

        };

        // 登出
        const Logout = () => {

          globObj.username = "";
          globObj.password = "";

          password.value = "";
          areaList.value = [];

          currentPage.value = 'login';

        };
        
        // 生成密码函数
        const generatePassword = (rules, seed) => {
          
          const uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
          const lowercase = 'abcdefghijklmnopqrstuvwxyz';
          const numbers = '0123456789';
          
          let charsets = [];
          let password = '';

          // 确保至少包含一个要求的字符类型
          if (rules.uppercase) charsets.push(uppercase);
          if (rules.lowercase) charsets.push(lowercase);
          if (rules.numbers) charsets.push(numbers);
          if (rules.space) charsets.push(" ");

          for(let i = 0; i < 4; i++) {
            let key = "symbols" + (i + 1).toString();
            if(rules[key] != null && rules[key]) {
              charsets.push(passwordRules[key].label);
            }
          }

          if(rules.extra_chars != null) {
            charsets.push(rules.extra_chars);
          }
          
          // 如果没有选择任何字符类型，使用默认字符集
          if (charsets.length == 0) {
            charsets.push(uppercase);
            charsets.push(lowercase);
            charsets.push(numbers);
          }

          if(rules.ignore_chars != null) {
            for (let i = 0; i < rules.ignore_chars.length; i++) {
              let char = rules.ignore_chars[i];
              var regex = new RegExp(char, 'g');
              for(let j = charsets.length - 1; j >= 0; j--) {
                charsets[j] = charsets[j].replace(regex, '');
                if(charsets[j].length == 0) {
                  charsets.splice(j, 1);
                }
              }
            }
          }

          let key = CryptoJS.SHA256(globObj.password + "_Thisismigicvalue_" + seed).toString();
          
          // TODO: 1.固定随机数种子 2.在可用字符中随机选择 3.若当前字符中有超过两个一样的字符或相邻字符一样或相邻两个字符在ascii表中相邻则丢弃本次选择的字符
          for(let i = 0; i < key.length; i++) {
            
          }

          // 每种至少有一个字符
          if(rules.leastOne) {
            // TODO: 先从charsets每组中随机一个字符，后面流程与非逻辑一致
          }

          return password;

        };
        
        // 计算删除项名称
        const deleteItemName = computed(() => {
          if (deleteIndex.value >= 0 && areaList.value[deleteIndex.value]) {
            return areaList.value[deleteIndex.value].name;
          }
          return '';
        });
        
        // 初始化加载数据
        onMounted(() => {
          
        });
        
        return {
          currentPage,
          username,
          password,
          areaList,
          showEditPanel,
          isEditing,
          showDeleteConfirm,
          showToast,
          showGeneratedPassword,
          generatePassword,
          longPressIndex,
          passwordRules,
          currentItem,
          deleteItemName,
          showScrollHint,
          login,
          openAddPanel,
          openEditPanel,
          closeEditPanel,
          addNote,
          removeNote,
          saveItem,
          confirmDelete,
          deleteItem,
          togglePasswordVisibility,
          copyPassword,
          startLongPress,
          endLongPress,
          exportData,
          importData,
          Logout,
        };
      }
    }).mount('#app');
  </script>
</body>
</html>